package org.jobtask.listener;

import java.awt.Font;
import java.awt.Point;
import java.awt.TrayIcon;
import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Observable;
import java.util.Observer;

import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JToggleButton;
import javax.swing.event.DocumentEvent;
import javax.swing.event.ListSelectionEvent;
import javax.swing.text.BadLocationException;

import org.jobtask.config.JobTaskConfig;
import org.jobtask.config.ObjectFactory;
import org.jobtask.config.ResourceMessages;
import org.jobtask.iface.ControlListener;
import org.jobtask.iface.Scheduling;
import org.jobtask.io.JobIO;
import org.jobtask.schedule.ExceptionJobStack;
import org.jobtask.schedule.JobState;
import org.jobtask.schedule.JobTask;
import org.jobtask.schedule.KeyValue;
import org.jobtask.schedule.Nurse;
import org.jobtask.schedule.TaskGroup;
import org.jobtask.ui.CommonComponents;
import org.jobtask.ui.LogViewPort;
import org.jobtask.ui.TaskAbout;
import org.jobtask.ui.TaskEditDialog;
/**
 * @category JobTask 
 * @version 1.2
 * @author 张波 Bob
 * @Description
 * <p>
 *      此类是应用程序的控制中心,这是一个监听器,监视界面上的所有界面控件的用户操作,在适当的时候做出反应
 * </p>
 *
 */
public class Monitor extends WindowAdapter implements ControlListener,Observer {
	
	/**
	 * taskStack 存放当前已启动的线程
	 */
	private HashMap<String,Scheduling> taskStack; 
	private boolean isStop=true;
	private Nurse nurse=null;
	/**
	 * 定义自监控线程对象
	 * @return
	 */
	public HashMap<String, Scheduling> getTaskStack() {
		return taskStack;
	}

	private CommonComponents components=null;
	public CommonComponents getComponents() {
		return components;
	}

	/**
	 * taskGroup 任务列表组
	 */
	private TaskGroup taskGroup=null;
	private JobIO jio=null;
	private boolean isScroll=true;
	private boolean isMinimize=false;
	private int firstItem=0;
	public Monitor(CommonComponents comp){
		components=comp;
		taskStack=new HashMap<String, Scheduling>();
		jio=new JobIO();
		this.fillTaskGroup();
	}
	
	private void fillTaskGroup(){
		this.jio.loadDom();
		taskGroup=this.jio.getTaskGroup();
		this.components.addGroupsToList(taskGroup.getGroups());
		this.components.addGroupItemsToList(taskGroup.getGroupItems(this.components.getCurrentSelectGroup()));
		if(!this.components.getListModel().isEmpty()){
		   this.components.getCurrentSelectItem()[0].getLogDocument().addDocumentListener(this);
		}
		this.setStatusTaskScript();
	}
	
	
	private void setState(){
		JobTask[] task=this.components.getCurrentSelectItem();
		for(JobTask job:task){
			this.components.getCtrlBut().setSelected(job.getState().equals(JobState.RUNING));
			this.components.startButtonStateChange();
		}
	}
	
	
	public void setStatusTaskScript(){
		int tc=this.taskGroup.getGroupTotal();
		this.components.getTotalCountLab().setText(tc+"");
		this.components.getStartCountLab().setText(this.taskStack.size()+"");
		this.components.getStopCountLab().setText((tc-this.taskStack.size())+"");
	}
	
	private void createTask(){
		TaskEditDialog taskEdit=new TaskEditDialog();
		if(taskEdit.openEditDialog()){
			JobTask task=taskEdit.getJobTask();
			task.getLogDocument().addDocumentListener(this);
			this.components.addGroupItemToList(task);
			this.components.displayInfo();
			this.components.getText().setStyledDocument(task.getLogDocument());
			this.setState();
			this.taskGroup.addGroupItem(this.components.getCurrentSelectGroup(), task);
			this.jio.addJob(task, this.components.getCurrentSelectGroup());
		}
	}
	
	private void builderGroupMenu(){
		this.components.getMoveToMenu().removeAll();
		KeyValue[] keyValue=this.taskGroup.getGroups();
		JMenuItem[] menu=new JMenuItem[keyValue.length];
		for(int index=0;index<menu.length;index++){
			if(this.components.getCurrentSelectGroup().equals(keyValue[index])) continue;
			menu[index]=new JMenuItem(keyValue[index].getValue().toString());
			menu[index].setName(keyValue[index].getKey().toString());
			menu[index].setActionCommand("moveGroup");
			menu[index].addActionListener(this);
			this.components.getMoveToMenu().add(menu[index]);
		}
	}
	
	/**
	 * 检查返回的任务列表中是否还有正在运行的
	 */
	private boolean hasRunJob(JobTask[] jobs){
		for(JobTask job:jobs){
			if(job.getState().equals(JobState.RUNING)||job.getState().equals(JobState.PAUSE)){
				return true;
			}
		}
		return false;
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		if(e.getActionCommand().equals("addTask")||e.getActionCommand().equals("newMenu")){
			this.createTask();
		}else if(e.getActionCommand().equals("delTask")||e.getActionCommand().equals("removeMenu")){
			if(this.components.getListModel().isEmpty()||this.components.getTaskList().isSelectionEmpty()){
				JOptionPane.showMessageDialog(components.getWin(), ResourceMessages.getString("Monitor.0"), ResourceMessages.getString("Monitor.1"),JOptionPane.WARNING_MESSAGE);
				return;
			}
			JobTask[] job=this.components.getCurrentSelectItem();
			if(this.hasRunJob(job)){
				JOptionPane.showMessageDialog(components.getWin(),ResourceMessages.getString("Monitor.2") ,ResourceMessages.getString("Monitor.1"),JOptionPane.WARNING_MESSAGE);
			}else{
				for(JobTask j:job){
					j.getLogDocument().removeDocumentListener(this);
					this.taskGroup.removeGroupItem(this.components.getCurrentSelectGroup(),this.components.getTaskList().getSelectedIndex());
					this.jio.removeJob(j, this.components.getCurrentSelectGroup());
					this.components.removeGroupItemFromList();
					this.components.displayInfo();
				}
			}
		}else if(e.getActionCommand().equals("ctrl")){
			JToggleButton tb=(JToggleButton)e.getSource();
			if(this.components.getListModel().isEmpty()||this.components.getTaskList().isSelectionEmpty()){
				JOptionPane.showMessageDialog(components.getWin(), ResourceMessages.getString("Monitor.3"), ResourceMessages.getString("Monitor.1"),JOptionPane.WARNING_MESSAGE);
				tb.setSelected(false);
				this.createTask();
			}else{
				//启动任务
				JobTask[]  jt=this.components.getCurrentSelectItem();
				this.components.getTaskList().setSelectedIndex(this.firstItem);
				for(JobTask job:jt){
					if(tb.isSelected()){
						if(job.getState().equals(JobState.STOP)){
							Scheduling scheduling=(Scheduling)ObjectFactory.getInstance(JobTaskConfig.getString(job.getTaskType()),job);
							if(scheduling instanceof Observable){((Observable) scheduling).addObserver(this);}
							new Thread(scheduling).start();
							this.taskStack.put(job.getSequece(),scheduling);
							this.components.getText().setDocument(job.getLogDocument());
							ExceptionJobStack.removeJob(job);
						}else{
							this.setState();
							JOptionPane.showMessageDialog(components.getWin(), ResourceMessages.getString("Monitor.4"), ResourceMessages.getString("Monitor.1"),JOptionPane.WARNING_MESSAGE);
						}
					}else{
						if(this.taskStack.get(job.getSequece())!=null)
							this.taskStack.get(job.getSequece()).halt();
						this.taskStack.remove(job.getSequece());
						ExceptionJobStack.addExpJob(job);
					}
				}
				this.components.startButtonStateChange();
				this.components.changeTableProperty(tb.isSelected());
			}
		}else if(e.getActionCommand().equals("clear")){
			if(this.components.getListModel().isEmpty()){
				JOptionPane.showMessageDialog(components.getWin(),ResourceMessages.getString("Monitor.5"),ResourceMessages.getString("Monitor.1"),JOptionPane.WARNING_MESSAGE);
			}else{
				JobTask  jt=this.components.getCurrentSelectItem()[0];
				try {
					jt.clearLog(true);
				} catch (BadLocationException e1) {
					e1.printStackTrace();
				}
			}
		}else if(e.getActionCommand().equals("addGoupBut")){
			String content=JOptionPane.showInputDialog(components.getWin(),ResourceMessages.getString("Monitor.6"),ResourceMessages.getString("Monitor.7"), JOptionPane.QUESTION_MESSAGE);
			if(content!=null&&!content.equals("")){
				KeyValue newGroup=new KeyValue("G"+System.currentTimeMillis(),content);
				this.components.addGroupToList(newGroup);
				this.taskGroup.addGroup(newGroup);
				this.jio.addGroup(newGroup);
				this.components.getListModel().clear();
			}
		}else if(e.getActionCommand().equals("delGoupBut")){
			if(this.components.getTaskGroupList().getSelectedIndex()==0) return;
			int option=JOptionPane.showConfirmDialog(components.getWin(),ResourceMessages.getString("Monitor.8"), ResourceMessages.getString("Monitor.9"),JOptionPane.OK_CANCEL_OPTION ,JOptionPane.WARNING_MESSAGE);
			if(option==JOptionPane.OK_OPTION){
				KeyValue oldGroup=this.components.getCurrentSelectGroup();
				this.components.removeGroupFromList();
				this.components.addGroupItemsToList(this.taskGroup.getGroupItems(this.components.getCurrentSelectGroup()));
				this.taskGroup.removeGroup(oldGroup);
				this.jio.removeGroup(oldGroup);
			}
		}else if(e.getActionCommand().equals("logsMenu")){
			if(!LogViewPort.isOpen){
			    new LogViewPort(this.taskGroup.getFullTask());
			}
		}else if(e.getActionCommand().equals("modifyTaskMenu")||e.getActionCommand().equals("modifyMenu")){
			JobTask[] job=this.components.getCurrentSelectItem();
			
			 if(this.components.getCurrentSelectItem()[0].getState().equals(JobState.STOP)){
				    TaskEditDialog taskEdit=new TaskEditDialog();
				    taskEdit.setTitle(ResourceMessages.getString("Monitor.23"));
					if(taskEdit.openEditDialog(this.components.getCurrentSelectItem()[0])){
						JobTask task=taskEdit.getJobTask();
						this.components.getCurrentSelectItem()[0].getLogDocument().removeDocumentListener(this);
						this.taskGroup.removeGroupItem(this.components.getCurrentSelectGroup(),this.components.getTaskList().getSelectedIndex());
						this.jio.removeJob(this.components.getCurrentSelectItem()[0], this.components.getCurrentSelectGroup());
						this.components.removeGroupItemFromList();
						
						task.getLogDocument().addDocumentListener(this);
						this.components.getText().setStyledDocument(task.getLogDocument());
						this.taskGroup.addGroupItem(this.components.getCurrentSelectGroup(), task);
						this.jio.addJob(task, this.components.getCurrentSelectGroup());
						this.components.addGroupItemToList(task);
						this.setState();
						this.components.displayInfo();
					}
			 }else{
				 JOptionPane.showMessageDialog(components.getWin(),ResourceMessages.getString("Monitor.22"),ResourceMessages.getString("Monitor.13"),JOptionPane.WARNING_MESSAGE);
			 }
		}else if(e.getActionCommand().equals("saveMenu")){
			   jio.saveJob();
			  JOptionPane.showMessageDialog(components.getWin(),ResourceMessages.getString("Monitor.21"),ResourceMessages.getString("Monitor.20"),JOptionPane.INFORMATION_MESSAGE);
		}else if(e.getActionCommand().equals("reloadMenu")){
			if(this.taskStack.size()>0){
				JOptionPane.showMessageDialog(components.getWin(),ResourceMessages.getString("Monitor.19"),ResourceMessages.getString("Monitor.13"),JOptionPane.WARNING_MESSAGE);
			}else{
				int option=JOptionPane.showConfirmDialog(components.getWin(),ResourceMessages.getString("Monitor.18"),ResourceMessages.getString("Monitor.13"),JOptionPane.YES_NO_OPTION,JOptionPane.WARNING_MESSAGE);
				 if(option==JOptionPane.YES_OPTION){
					 this.components.getGroupModel().clear();
					 this.fillTaskGroup();
				 }
			}
		}else if(e.getActionCommand().equals("minimiToTrayMenu")){
			 this.isMinimize=!this.isMinimize;
			 this.components.getMinimiToTrayMenu().setText(this.isMinimize?ResourceMessages.getString("Monitor.15"):ResourceMessages.getString("Monitor.14"));
		}else if(e.getActionCommand().equals("nurseMenu")){
			if(this.isStop){
				nurse=new Nurse(this);
				nurse.setDaemon(true);
			    nurse.start();
			    this.components.getNurseMenu().setText(ResourceMessages.getString("CommonComp.34"));
			    this.isStop=false;
			}else{
				nurse.halt();
				this.isStop=true;
				this.components.getNurseMenu().setText(ResourceMessages.getString("CommonComp.33"));
				nurse=null;
			}
		}else if(e.getActionCommand().equals("winTopMenu")){
			 if(this.components.getWin().isAlwaysOnTopSupported()){
				 this.components.getWin().setAlwaysOnTop(!this.components.getWin().isAlwaysOnTop());
				 this.components.getWinTopMenu().setText(this.components.getWin().isAlwaysOnTop()?ResourceMessages.getString("Monitor.16"):ResourceMessages.getString("Monitor.17"));
			 }
		}else if(e.getActionCommand().equals("helpMenu")){
			 try {
				Runtime.getRuntime().exec(JobTaskConfig.getString("helpfile"));
			} catch (IOException e1) {
				e1.printStackTrace();
			}
		}else if(e.getActionCommand().equals("aboutMenu")){
			TaskAbout about=new TaskAbout();
			about.showDialog(this.components.getWin());
		}else if(e.getActionCommand().equals("exitMenu")){
			int option=JOptionPane.showConfirmDialog(this.components.getWin(),ResourceMessages.getString("Monitor.12"),ResourceMessages.getString("Monitor.13"),JOptionPane.YES_NO_OPTION,JOptionPane.WARNING_MESSAGE);
			 if(option==JOptionPane.YES_OPTION){
				 jio.saveJob(); 
				 System.exit(0);
			 }
		}else if(e.getActionCommand().equals("moveGroup")){
			    JMenuItem source=(JMenuItem)e.getSource();
			    JobTask[] jobtask=this.components.getCurrentSelectItem();
			    int[] indices=this.components.getTaskList().getSelectedIndices();
			    KeyValue  targetGroup=new KeyValue(source.getName(),"");
			    for(int index=jobtask.length-1;index>=0;index--){
			    	this.taskGroup.addGroupItem(targetGroup,jobtask[index]);
			    	this.taskGroup.removeGroupItem(this.components.getCurrentSelectGroup(),indices[index]);
			    	this.jio.moveJobToGroup(jobtask[index], this.components.getCurrentSelectGroup(),targetGroup);
			    	this.components.removeGroupItemFromList();
			    }
				this.components.displayInfo();
		}else if(e.getActionCommand().equals("selectall")){
			this.components.selectAll(this.firstItem);
		}
	
		this.setStatusTaskScript();
	}

	@Override
	public void valueChanged(ListSelectionEvent e) {
		if(e.getValueIsAdjusting()){
			this.isScroll=false;
			if(e.getSource()==this.components.getTaskGroupList()){
				KeyValue gp=(KeyValue)this.components.getTaskGroupList().getSelectedValue();
				int size=this.components.addGroupItemsToList(this.taskGroup.getGroupItems(gp));
				this.components.getSelectAll().setEnabled(size>=1);
				this.components.wasEnabled(size>=1);
				return;
			}
			if(!this.components.getTaskList().isSelectionEmpty()&&this.components.getCurrentSelectItem().length==1){
				this.components.getText().getDocument().removeDocumentListener(this);
				this.components.displayInfo();
				this.components.getCurrentSelectItem()[0].getLogDocument().addDocumentListener(this);
				this.components.getText().setDocument(this.components.getCurrentSelectItem()[0].getLogDocument());
				this.components.wasEnabled(true);
				this.setState();
				this.firstItem=this.components.getTaskList().getSelectedIndex();
			}else{
				ArrayList<Integer> itemIndexs=new ArrayList<Integer>();
				this.components.wasEnabled(false);
				int[] indices=this.components.getTaskList().getSelectedIndices();
				JobTask firstJob=this.components.getSelectJobByIndex(this.firstItem);
				for(int index=0;index<indices.length;index++){
						JobTask tempJob=this.components.getSelectJobByIndex(indices[index]);
						if(tempJob.getRunStatus()==firstJob.getRunStatus()){
							itemIndexs.add(indices[index]);
						}
				}
				this.components.getTaskList().removeListSelectionListener(this);
				int[] iCount=new int[itemIndexs.size()];
				for(int i=0;i<iCount.length;i++){
					iCount[i]=itemIndexs.get(i).intValue();
				}
				this.components.getTaskList().setSelectedIndices(iCount);
				this.components.getTaskList().addListSelectionListener(this);
			}
            this.isScroll=true;
            this.setStatusTaskScript();
		}
	}
	

	@Override
	public void insertUpdate(DocumentEvent e) {
		try{
			if(this.isScroll&&e.getDocument()==this.components.getCurrentSelectItem()[0].getLogDocument()){
		     this.components.getText().setCaretPosition(e.getDocument().getLength()); 
			}
		}catch(Exception ex){
			
		}
		this.setStatusTaskScript();
	}

	@Override
	public void removeUpdate(DocumentEvent e) {
		if(e.getDocument()==this.components.getCurrentSelectItem()[0].getLogDocument()){
			JToggleButton tb=this.components.getCtrlBut();
			this.setState();
			this.components.changeTableProperty(tb.isSelected());
		}
		this.setStatusTaskScript();
	}

	@Override
	public void changedUpdate(DocumentEvent e) {
	}

	
	private boolean isEnterButton2=false;
	private Point point=null;
	
	@Override
	public void mouseDragged(MouseEvent e) {
		if(isEnterButton2){
			int  x=(e.getPoint().x-this.point.x);
			int fontSize=this.components.getText().getFont().getSize();
			if(x>0){
				if(fontSize<=72) fontSize++;
				point=e.getPoint();
			}else{
				if(fontSize>=8) fontSize--;
				point=e.getPoint();
			}
			this.components.getText().setFont(new Font("Sans Serif", Font.PLAIN, fontSize));
		}
		
	}

	@Override
	public void mouseMoved(MouseEvent e) {
	}

	@Override
	public void mouseClicked(MouseEvent e) {
		if(e.getSource()==this.components.getTaskGroupList()){
			if(this.components.getTaskGroupList().getSelectedIndex()==0) return;
			if(e.getButton()==e.BUTTON1&&e.getClickCount()==2){
				String content=(String)JOptionPane.showInputDialog(this.components.getWin(),ResourceMessages.getString("Monitor.10"),ResourceMessages.getString("Monitor.11"), JOptionPane.QUESTION_MESSAGE,null,null,this.components.getCurrentSelectGroup());
				if(content!=null&&!content.equals("")){
					KeyValue kv=this.components.getCurrentSelectGroup();
					kv.setValue(content);
					this.taskGroup.renameGroup(kv);
					this.jio.modifyGrouupNode(kv);
				}
			}
		}else if(e.getSource() instanceof TrayIcon){
			this.components.palletized(this,false);
			this.components.getWin().setExtendedState(JFrame.NORMAL);
			this.components.getWin().setVisible(true);
		}
	}

	@Override
	public void mousePressed(MouseEvent e) {
		if(e.getButton()==MouseEvent.BUTTON3){
		   this.isEnterButton2=true;
		   this.point=e.getPoint();
		   if(e.getSource()==this.components.getTaskList()){
			   if(this.components.getListModel().isEmpty()){
				   this.components.getMoveToMenu().setEnabled(false);
			   }else{
				   this.components.getMoveToMenu().setEnabled(true);
			      this.builderGroupMenu();
			   }
		      this.components.getTaskPopupMenu().show(this.components.getTaskList(),e.getX(),e.getY());
		   }
		}
	}

	@Override
	public void mouseReleased(MouseEvent e) {
		if(e.getButton()==MouseEvent.BUTTON3){
			   this.isEnterButton2=false;
			   this.point=null;
		}
	}

	@Override
	public void mouseEntered(MouseEvent e) {
	}

	@Override
	public void mouseExited(MouseEvent e) {
	}
	
	public void windowClosing(java.awt.event.WindowEvent e) {
		 int option=JOptionPane.showConfirmDialog(this.components.getWin(),ResourceMessages.getString("Monitor.12"),ResourceMessages.getString("Monitor.13"),JOptionPane.YES_NO_OPTION,JOptionPane.WARNING_MESSAGE);
		 if(option==JOptionPane.YES_OPTION){
			 jio.saveJob(); 
			 System.exit(0);
		 }
	}
	
	@Override
	public void windowIconified(WindowEvent e) {
		if(this.isMinimize){
			this.components.getWin().dispose();//setVisible(false);
			this.components.palletized(this,true);
		}
	}
	
	@Override
	public void update(Observable o, Object arg) {
		JobTask jt=(JobTask)arg;
		this.setState();
		if(this.taskStack.get(jt.getSequece())!=null)
			this.taskStack.get(jt.getSequece()).halt();
		this.taskStack.remove(jt.getSequece());
		this.setStatusTaskScript();
		this.components.changeTableProperty(false);
		jt.setState(JobState.STOP);
	}
	
}

